package com.yuanshen.equip;


import com.alibaba.excel.EasyExcel;
import com.yuanshen.equip.dto.EquipRules;
import com.yuanshen.equip.dto.HeroValidProperty;
import com.yuanshen.equip.enums.EquipType;
import com.yuanshen.equip.enums.Hero;
import com.yuanshen.equip.enums.PropertyType;
import com.yuanshen.equip.vo.HeroEquipExcelVo;


import java.util.ArrayList;
import java.util.List;

/**
 * 主程序
 *
 * @author Administrator
 * @date 2023/2/9 14:09
 */
public class YuanShenMain {

    /**
     * 导出表格
     */
    public static void main(String[] args) {
        List<HeroEquipExcelVo> list = new ArrayList<>();

        for (Hero hero : Hero.values()) {
            // 圣遗物类型
            for (EquipType item : EquipType.values()) {
                List<PropertyType> mainProperty = EquipRules.getMainProperty(item);
                List<PropertyType> otherProperty = EquipRules.getOtherProperty();

                List<HeroEquipExcelVo> excelList = getExcelList(item, mainProperty, otherProperty, hero);
                list.addAll(excelList);
            }
        }

        String fileName = getPath() + "圣遗物搭配" + System.currentTimeMillis() + ".xlsx";
        System.out.println(fileName);
        // 这里 需要指定写用哪个class去写，然后写到第一个sheet，名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(fileName, HeroEquipExcelVo.class)
                .sheet("圣遗物搭配")
                .doWrite(list);
    }


    /**
     * 得到excel列表
     *
     * @param mainProperty  主词条集合
     * @param otherProperty 副词条集合
     * @param equipType     装备类型
     * @param hero          英雄
     * @return {@link List}<{@link HeroEquipExcelVo}>
     */
    public static List<HeroEquipExcelVo> getExcelList(EquipType equipType, List<PropertyType> mainProperty,
                                                      List<PropertyType> otherProperty, Hero hero) {
        List<HeroEquipExcelVo> result = new ArrayList<>();

        // 副属性是固定的
        List<List<PropertyType>> allPossibilities = getAllPossibilities(otherProperty);

        for (PropertyType item : mainProperty) {

            for (List<PropertyType> list : allPossibilities) {

                // 副词条里不能包括主词条
                if (list.contains(item)) {
                    continue;
                }

                // 有效词条为0 不需要打打印出来
                int number = HeroValidProperty.calValidNumber(hero, list);
                if (number == 0) {
                    continue;
                }

                HeroEquipExcelVo excelVo = new HeroEquipExcelVo();
                excelVo.setEquipType(equipType.getName());
                excelVo.setEquipmentMainAttr(item.getName());
                excelVo.setEquipmentAttr_1(list.get(0).getName());
                excelVo.setEquipmentAttr_2(list.get(1).getName());
                excelVo.setEquipmentAttr_3(list.get(2).getName());
                excelVo.setEquipmentAttr_4(list.get(3).getName());

                list.add(item);
                excelVo.setHeroName(hero.getName());
                excelVo.setValidAttr(number);

                result.add(excelVo);
            }
        }

        return result;
    }


    /**
     * 从给定的集合中，获取四个不同的属性，忽略顺序的影响，获取所有可能的结果
     *
     * @param propertyTypes 属性类型
     * @return {@link List}<{@link String}>
     */
    public static List<List<PropertyType>> getAllPossibilities(List<PropertyType> propertyTypes) {
        List<List<PropertyType>> result = new ArrayList<>();

        int[] arr = new int[propertyTypes.size()];
        for (PropertyType item : propertyTypes) {
            arr[item.ordinal()] = item.ordinal();
        }

        ArrayList<ArrayList<Integer>> subList = getSubList(arr);
        for (List<Integer> item : subList) {
            if (item.size() == 4) {
                List<PropertyType> list = new ArrayList<>();
                list.add(getPropertyForInt(item.get(0)));
                list.add(getPropertyForInt(item.get(1)));
                list.add(getPropertyForInt(item.get(2)));
                list.add(getPropertyForInt(item.get(3)));
                result.add(list);
            }
        }

        return result;
    }


    /**
     * 获取所有子集
     */
    public static ArrayList<ArrayList<Integer>> getSubList(int[] arr) {
        ArrayList<ArrayList<Integer>> allList = new ArrayList<>();
        int size = 1 << arr.length;// 2^n次方
        for (int mark = 0; mark < size; mark++) {
            ArrayList<Integer> aList = new ArrayList<>();
            for (int i = 0; i < arr.length; i++) {
                /* 重要：这句是最重要的代码:是 0-7 分别与运算 1，2，4
                 * 000 001 010 011 100 101 110 111
                 *
                 */
                if ((mark & (1 << i)) != 0) {
                    aList.add(arr[i]);
                }
            }
            allList.add(aList);
        }
        return allList;
    }


    /**
     * 数值映射成枚举
     *
     * @param ch ch
     * @return {@link PropertyType}
     */
    public static PropertyType getPropertyForInt(int ch) {
        for (PropertyType item : PropertyType.values()) {
            if (ch == item.ordinal()) {
                return item;
            }
        }

        return null;
    }


    /**
     * 获取路径
     *
     * @return {@link String}
     */
    public static String getPath() {
        return YuanShenMain.class.getResource("/").getPath();
    }
}
